﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Security;
using System.Net.Sockets;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using UMC.Data;

namespace UMC.Host
{


    public class HttpServier
    {

        static String _Server = Dns.GetHostName();
        public static String Server => _Server;
        ManualResetEvent mre = new ManualResetEvent(false);
        static HttpServier servier;
         UMC.Net.INetHandler handler;

        public static void Start(int port, UMC.Net.INetHandler  handler)
        {
            Console.WriteLine($"http://*:{port}");
            servier = new HttpServier();
            servier.handler = handler;
            if (Socket.OSSupportsIPv4)
            {
                var socket = new Socket(IPAddress.Any.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
                socket.Bind(new IPEndPoint(IPAddress.Any, port));
                socket.Listen(512);

                SocketAsyncEventArgs eventArgs = new SocketAsyncEventArgs();
                eventArgs.Completed += servier.Http;
                socket.AcceptAsync(eventArgs);
            }
            if (Socket.OSSupportsIPv6)
            {
                var socket = new Socket(IPAddress.IPv6Any.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
                socket.Bind(new IPEndPoint(IPAddress.IPv6Any, port));
                socket.Listen(512);

                SocketAsyncEventArgs eventArgs = new SocketAsyncEventArgs();
                eventArgs.Completed += servier.Http;
                socket.AcceptAsync(eventArgs);
            }


            while (_IsStop == false)
            {
                servier.mre.WaitOne(5000);
                try
                {
                    CheckLink();
                    UMC.Net.NetProxy.Check();

                }
                catch (Exception ex)
                {
                    UMC.Data.Utility.Error("Server", DateTime.Now, ex);
                }

                // servier.CloseLink();
            }

        }
        static bool _IsStop;
        public static void Stop()
        {
            _IsStop = true;
            servier.mre.Set();
        }

        private void Http(object sender, SocketAsyncEventArgs eventArgs)
        {
            do
            {
                var client = eventArgs.AcceptSocket;
                eventArgs.AcceptSocket = null;
                switch (eventArgs.SocketError)
                {
                    case SocketError.OperationAborted:
                        return;
                    case SocketError.Success:
                        if (client != null)
                        {
                            try
                            {
                                var ip = client.RemoteEndPoint as IPEndPoint;
                                new HttpSocket(client, client.LocalEndPoint.ToString(), ip.Address.ToString(), this.handler);
                            }
                            catch
                            {
                                client.Close();
                                client.Dispose();
                            }
                        }
                        break;

                }

            } while (!((Socket)sender).AcceptAsync(eventArgs));
        }


        // void CloseLink()
        // {
        //     var ms = httpMimes.Values.ToArray();
        //     foreach (var b in ms)
        //     {
        //         try
        //         {
        //             if (b.Connected == false)
        //             {
        //                 b.Dispose();
        //             }
        //             else if (b.TimeOut < 30)
        //             {
        //                 b.Dispose();

        //             }
        //         }
        //         catch
        //         {

        //         }
        //     }

        // }
        static void CheckLink()
        {
            var time = UMC.Data.Utility.TimeSpan();
            var ms = httpMimes.Values.ToArray();

            HttpSocket link;
            foreach (var b in ms)
            {
                try
                {
                    if ((b.ActiveTime + b.TimeOut) < time)
                    {
                        httpMimes.TryRemove(b.Id, out link);
                        if (b.TimeOut > 30)
                        {
                            b.Error(504, "Gateway Timeout");
                        }
                        else
                        {
                            b.Dispose();
                        }
                    }
                    else if (b.Connected == false)
                    {
                        httpMimes.TryRemove(b.Id, out link);
                        b.Dispose();
                    }
                }
                catch
                {

                }
            }
        }
        internal static ConcurrentDictionary<int, HttpSocket> httpMimes = new ConcurrentDictionary<int, HttpSocket>();
    }



}
